package com.upsuns.nio;

import java.awt.RenderingHints.Key;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import com.upsuns.util.QueryHandler;

/**
 *@Description:<p>TimeServer处理器，NIO模型</p>
 *@author 王旭
 *@time 2016年3月17日 下午4:28:54
 */
public class TimeServerHandler implements Runnable {
	
	private Selector selector;
	
	private ServerSocketChannel serverChannel;
	
	private volatile boolean isStop;
	
	public TimeServerHandler(int port) {
		try {
			this.selector = Selector.open();
			this.serverChannel = ServerSocketChannel.open();
			this.serverChannel.configureBlocking(false);
			this.serverChannel.bind(new InetSocketAddress(port));
			this.serverChannel.register(selector, SelectionKey.OP_ACCEPT);
			System.out.println("服务器已开启，监听端口："+port);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	public void stop() {
		this.isStop = true;
	}


	@Override
	public void run() {
		
		while(!isStop) {
			try {
				selector.select(); //阻塞，直到有准备好的channel为止
				Set<SelectionKey> keySet = selector.selectedKeys();
				Iterator<SelectionKey> iterator = keySet.iterator();
				
				SelectionKey key = null;
				try {
					while(iterator.hasNext()) {
						key = iterator.next();
						iterator.remove();
						handleKey(key);
					}
				} catch (IOException e) {
					key.cancel();
				}
			} catch (IOException e) {
				e.printStackTrace();
				
				System.exit(1);
			}
		}
		
		//当isStop为true时关闭selector
		if(selector != null) {
			try {
				selector.close();
			} catch (IOException e) {
				e.printStackTrace();
				System.exit(1);
			}
		}
		
	}
	
	private void handleKey(SelectionKey key) throws IOException {
		if(!key.isValid()) {
			return ;
		}
		
		//处理新请求
		if(key.isAcceptable()) {
			ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
			SocketChannel socketChannel = serverChannel.accept();
			
			socketChannel.configureBlocking(false);
			socketChannel.register(selector, SelectionKey.OP_READ);
		}
		
		if(key.isReadable()) {
			SocketChannel socketChannel = (SocketChannel) key.channel();
			ByteBuffer rBuffer = ByteBuffer.allocate(1024);
			int byteCnt = socketChannel.read(rBuffer);
			
			if(byteCnt <= 0) {
				return ; //未读到任何数据
			}
			
			rBuffer.flip(); //准备读数据
			byte[] bytes = new byte[rBuffer.remaining()];
			rBuffer.get(bytes); //把数据读入byte数组中
			
			String req = new String(bytes, "utf-8"); //把读到的数据转换成字符串
			
			String resp = QueryHandler.handleQuery(req);
			//没有可响应的数据
			if(resp == null || resp.length() <= 0) {
				return ;
			}
			//向客户端发送响应
			byte[] respBytes = resp.getBytes();
			ByteBuffer wBuffer = ByteBuffer.allocate(respBytes.length);
			
			wBuffer.put(respBytes);
			wBuffer.flip(); //准备读数据
			
			socketChannel.write(wBuffer);
		}
	}
	
	
	

	
	
}
